﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;

namespace Medianamik.Core
{
    public class SubEntityCollection<TOwner, TItem> : KeyedCollection<Guid, TItem>
        where TOwner : IEntity
        where TItem : SubEntity<TItem, TOwner>
    {
        #region Fields

        #endregion

        #region .ctors

        public SubEntityCollection(TOwner owner, IEnumerable<TItem> items)
            : this(owner)
        {
            AddRange(items);
        }

        public SubEntityCollection(TOwner owner)
            : base(null, 0)
        {
            if (owner == null)
                throw new ArgumentNullException("owner");

            Owner = owner;
        }

        #endregion

        #region Overrides

        protected override void InsertItem(int index, TItem item)
        {
            item.Owner = Owner;
            base.InsertItem(index, item);
        }

        protected override void RemoveItem(int index)
        {
            var item = Items[index];
            base.RemoveItem(index);
            _removed.Add(item);

        }
        protected override void ClearItems()
        {
            _removed.AddRange(this.Items);
            base.ClearItems();
        }

        #endregion

        #region Methods

        public virtual void AddRange(IEnumerable<TItem> items)
        {
            foreach (var item in items)
            {
                item.Owner = Owner;
                Add(item);
            }
        }

        //public TItem this[string name]
        //{
        //    get
        //    {
        //        var property = this.FirstOrDefault(p => p.Name.Equals(name, 
        //            StringComparison.OrdinalIgnoreCase));

        //        if (property == null)
        //            throw new CoreException("No property with the name " + name + " was found");

        //        return property;
        //    }
        //}

        //public bool Exists(string name)
        //{
        //    return Items.Any(p => p.Name.Equals(name, StringComparison.OrdinalIgnoreCase));
        //}

        public void ForEach(Action<TItem> action)
        {
            foreach (var item in Items)
            {
                action(item);
            }
        }

        public ReadOnlySubEntityCollection<TOwner, TItem> AsReadOnly()
        {
            return new ReadOnlySubEntityCollection<TOwner, TItem>(this);
        }

        protected override Guid GetKeyForItem(TItem item)
        {
            return item.ID;
        }

        #endregion

        #region Properties

        public TOwner Owner { get; protected set;}

        private List<TItem> _removed = new List<TItem>();
        internal ReadOnlyCollection<TItem> Removed
        {
            get{return _removed.AsReadOnly();}
        }

        #endregion
    }

    public class ReadOnlySubEntityCollection<TOwner, TItem> : SubEntityCollection<TOwner, TItem>
        where TOwner : IEntity
        where TItem : SubEntity<TItem, TOwner>
    {
        public ReadOnlySubEntityCollection(SubEntityCollection<TOwner, TItem> subEntityCollection)
            : base(subEntityCollection.Owner, subEntityCollection)
        {
            
        }

        protected override void InsertItem(int index, TItem item)
        {
            throw new InvalidOperationException("Cannot insert item on a read-only collection.");
        }

        public override void AddRange(IEnumerable<TItem> items)
        {
            throw new InvalidOperationException("Cannot insert items on a read-only collection.");
        }

        protected override void ClearItems()
        {
            throw new InvalidOperationException("Cannot clear items on a read-only collection.");
        }
    }
}
